package com.xbongbong.paas.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.ExcelConstant;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.exception.ExcelTitleCheckException;
import com.xbongbong.paas.help.ImportRedisHelper;
import com.xbongbong.paas.help.ImportSendHelper;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.dto.ImportFormDataDTO;
import com.xbongbong.paas.pojo.imports.CellTitlePojo;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.service.HandleImportService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.enums.errorcodes.ImportErrorCodeEnum;
import com.xbongbong.saas.constant.export.ImportConstant;
import com.xbongbong.saas.service.toolbox.help.PackageStatusHelp;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * Excel读取工具类
 * @author 魏荣杰
 * @date 2019/11/21 2:32 下午
 * @since v4.6.0
 * @version v4.6.0
 */
public class ExcelReaderUtil {

    public static void readXlsxExcel(InputStream inputStream, ExcelReadDataDelegated excelReadDataDelegated, int startRowIndex, List<FieldAttrEntityForImport> fieldAttrEntityList, ImportFormDataDTO importFormDataDTO, ImportSendHelper importSendHelper, HandleImportService handleImportService, PaasRedisHelper paasRedisHelper, ImportRedisHelper importRedisHelper, PackageStatusHelp packageStatusHelp) throws IOException, InvalidFormatException, XbbException {
        new ExcelXlsxReader(inputStream, excelReadDataDelegated, startRowIndex, fieldAttrEntityList, importFormDataDTO, importSendHelper, handleImportService, paasRedisHelper, importRedisHelper, packageStatusHelp).read();
    }

    /**
     * Description: 封装表头
     * @param titleLists
     * @param fieldAttrEntityForImportList
     * @param titleLength
     * @return java.util.List<com.xbongbong.paas.pojo.imports.CellTitlePojo>
     * @author 魏荣杰
     * @date 2019/11/19 5:13 下午
     * @since v4.6.0
     */
    public static List<CellTitlePojo> getCellTitlePojoList(List<List<String>> titleLists, List<FieldAttrEntityForImport> fieldAttrEntityForImportList, int titleLength) throws ExcelTitleCheckException {
        if (Objects.isNull(titleLists)) {
            // 提示表头获取失败
            throw new ExcelTitleCheckException(ImportErrorCodeEnum.API_ERROR_235002.getMsg());
        }

        // 读取到第一行数据的时候，表头已经加载完成，先对表头进行校验
        int titleDepth = titleLists.size();

        // 补充表头因合并单元格可能在末尾缺少单元格的情况，补空串
        for (int i = 0; i < titleDepth ; i++) {
            List<String> titles = titleLists.get(i);
            int size = titles.size();
            if (size < titleLength) {
                for (int j = titleLength - size ; j > 0 ; j--) {
                    titles.add("");
                }
            }
        }

        for (int i = 0 ; i < titleDepth ; i++) {
            List<String> titles = titleLists.get(i);
            for (int j = 0 ; j < titleLength ; j++) {
                String title = titles.get(j);
                if (i == 0) {
                    // 第一行标题补全
                    if (StringUtil.isEmpty(title)) {
                        if (j != 0) {
                            title = titles.get(j - 1);
                            titles.set(j, title);
                        } else {
                            throw new ExcelTitleCheckException(ImportErrorCodeEnum.API_ERROR_235002.getMsg());
                        }
                    }
                } else {
                    // 后面几行标题处理
                    if (StringUtil.isEmpty(title)) {
                        title = titleLists.get(i - 1).get(j);
                        String[] titleSplit = title.split(ExcelConstant.TITLE_SPLIT_REGEX);
                        if (titleSplit[0].contains(ImportConstant.TITLE_CAN_IMPORT_SEPARATELY)) {
                            if (j != 0) {
                                String[] split = titles.get(j - 1).split(ExcelConstant.TITLE_SPLIT_REGEX);
                                title = split[0] + ExcelConstant.TITLE_SPLIT + title;
                            } else {
                                throw new ExcelTitleCheckException(ImportErrorCodeEnum.API_ERROR_235002.getMsg());
                            }
                        } else {
                            if (i + 1 < titleDepth) {
                                String nextTitle = titleLists.get(i + 1).get(j);
                                if (StringUtil.isNotEmpty(nextTitle)) {
                                    if (j != 0) {
                                        String[] split = titles.get(j - 1).split(ExcelConstant.TITLE_SPLIT_REGEX);
                                        title = split[0] + ExcelConstant.TITLE_SPLIT + title;
                                    } else {
                                        throw new ExcelTitleCheckException(ImportErrorCodeEnum.API_ERROR_235002.getMsg());
                                    }
                                } else {
                                    title = titleLists.get(i - 1).get(j);
                                }
                            }
                        }
                        titles.set(j, title);
                    } else {
                        title += ExcelConstant.TITLE_SPLIT + titleLists.get(i -1).get(j);
                        titles.set(j, title);
                    }
                }
            }
        }

        return formatTitlePojoList(titleLists, fieldAttrEntityForImportList, titleLength, titleDepth);
    }

    public static List<CellTitlePojo> formatTitlePojoList(List<List<String>> titleLists, List<FieldAttrEntityForImport> fieldAttrEntityForImportList, int titleLength, int titleDepth) {
        List<CellTitlePojo> cellTitlePojoList = new ArrayList<>();
        String title = "";
        // 一级子表单(子表单才有父标题)
        String parentTitle = null;
        // 二级子表单
        String secondParentTitle = null;
        // 三级子表单
        String thirdParentTitle = null;

        List<String> titles = titleLists.get(titleDepth - 1);
        for (int i = 0; i < titleLength; i++) {
            String value = titles.get(i);
            String[] split = value.split(ExcelConstant.TITLE_SPLIT_REGEX);
            int length = split.length;
            switch (length) {
                case 1:
                    title = split[0];
                    break;
                case 2:
                    title = split[0];
                    parentTitle = split[1];
                    break;
                case 3:
                    title = split[0];
                    parentTitle = split[1];
                    secondParentTitle = split[2];
                    break;
                case 4:
                    title = split[0];
                    parentTitle = split[1];
                    secondParentTitle = split[2];
                    thirdParentTitle = split[3];
                    break;
                default:
                    break;
            }

            CellTitlePojo cellTitlePojo = new CellTitlePojo(title, parentTitle, secondParentTitle, thirdParentTitle, Integer.valueOf(i));
            cellTitlePojoList.add(cellTitlePojo);
            title = "";
            parentTitle = null;
            secondParentTitle = null;
            thirdParentTitle = null;
        }

        // 表头校验
        Set<String> titlePojoSet = new HashSet<>(cellTitlePojoList.size());
        cellTitlePojoList.forEach(item -> {
            String parent = item.getParentTitle() == null ? "" : item.getParentTitle();
            String secondParent = item.getSecondParentTitle() == null ? "" : item.getSecondParentTitle();
            String thirdParent = item.getThirdParentTitle() == null ? "" : item.getThirdParentTitle();
            titlePojoSet.add(parent + secondParent + thirdParent + item.getTitle());
        });
        List<CellTitlePojo> oldTitlePojoList = new ArrayList<>();
        getTitleList(oldTitlePojoList, fieldAttrEntityForImportList, null,null, null);
        Set<String> oldTitlePojoSet = new HashSet<>(oldTitlePojoList.size());
        oldTitlePojoList.forEach(item -> {
            String parent = item.getParentTitle() == null ? "" : item.getParentTitle();
            String secondParent = item.getSecondParentTitle() == null ? "" : item.getSecondParentTitle();
            String thirdParent = item.getThirdParentTitle() == null ? "" : item.getThirdParentTitle();
            oldTitlePojoSet.add(parent + secondParent + thirdParent + item.getTitle());
        });
        if (isIllegal(titlePojoSet, oldTitlePojoSet)) {
            throw new ExcelTitleCheckException(ImportErrorCodeEnum.API_ERROR_235002.getMsg());
        }
        return cellTitlePojoList;
    }

    private static void getTitleList(List<CellTitlePojo> titlePojoList, List<FieldAttrEntityForImport> fieldAttrList, String parentTitle, String secondParentTitle, String thirdParentTitle) {
        for (FieldAttrEntityForImport entity : fieldAttrList) {
            String title = entity.getAttrName();
            if (Objects.equals(entity.getFieldType(), FieldTypeEnum.SUB_FORM.getType())) {
                List<FieldAttrEntityForImport> subExplainList = JSONArray.parseArray(JSON.toJSONString(entity.getSubForm().getItems()), FieldAttrEntityForImport.class);
                getTitleList(titlePojoList, subExplainList, title, parentTitle, secondParentTitle);
            } else {
                CellTitlePojo cellTitlePojo = new CellTitlePojo(title, parentTitle, secondParentTitle, thirdParentTitle);
                titlePojoList.add(cellTitlePojo);
            }
        }
    }

    private static boolean isIllegal(Set<String> titlePojoSet, Set<String> oldTitlePojoSet) {
        for (String s : oldTitlePojoSet) {
            if (!titlePojoSet.contains(s)) {
                return true;
            }
        }
        return false;
    }


    /**
     * Description: 读取Excel，用sax方式,自己写的，合并单元格的处理缺失
     * @param fileName
     * @param excelReadDataDelegated
     * @author 魏荣杰
     * @date 2019/11/13 8:57 下午
     * @since v4.6.0
     */
    public static void readExcel(String fileName, ExcelReadDataDelegated excelReadDataDelegated) throws Exception {
        int totalRows;
        if (fileName.endsWith(ExcelConstant.EXCEL03_EXTENSION)) {
            //处理excel2003文件
            ExcelXlsListener excelXlsListener = new ExcelXlsListener(excelReadDataDelegated);
            totalRows = excelXlsListener.process(fileName);
        } else if (fileName.endsWith(ExcelConstant.EXCEL07_EXTENSION)) {
            //处理excel2007文件
            ExcelXlsxHandler excelXlsxHandler = new ExcelXlsxHandler(excelReadDataDelegated);
            totalRows = excelXlsxHandler.process(fileName);
        } else {
            throw new Exception(I18nMessageUtil.getMessage(I18nStringConstant.FILE_FORMAT_ERROR));
        }
    }

    /**
     * Description: 读取07版的Excel，官方测试用
     * @param fileName
     * @param excelReadDataDelegated
     * @param startRowIndex 数据开始的行数
     * @param fieldAttrList
     * @author 魏荣杰
     * @date 2019/11/18 2:39 下午
     * @since v4.6.0
     */
    @Deprecated
    public static void readExcelByXSSFSHandler(String fileName, ExcelReadDataDelegated excelReadDataDelegated, int startRowIndex, List<FieldAttrEntityForImport> fieldAttrList) throws Exception {
        //处理excel2007文件
        XlsxProcessUtil xlsxProcessUtil = new XlsxProcessUtil(excelReadDataDelegated);
        xlsxProcessUtil.processAllSheet(fileName, startRowIndex, fieldAttrList);
    }

    /**
     * Description: 读取07版的Excel，官方测试用
     * @param inputStream
     * @param excelReadDataDelegated
     * @param startRowIndex 数据开始的行数
     * @author 魏荣杰
     * @date 2019/11/18 2:39 下午
     * @since v4.6.0
     */
    @Deprecated
    public static void readExcelByXSSFSHandler(InputStream inputStream, ExcelReadDataDelegated excelReadDataDelegated, int startRowIndex, List<FieldAttrEntityForImport> fieldAttrEntityList, ImportFormDataDTO importFormDataDTO) throws Exception {
        //处理excel2007文件
        XlsxProcessUtil xlsxProcessUtil = new XlsxProcessUtil(excelReadDataDelegated);
        xlsxProcessUtil.processAllSheet(inputStream, startRowIndex, fieldAttrEntityList, importFormDataDTO);
    }
}
